/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package nsip.scheduling;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import nsip.model.Item;
import org.uncommons.maths.random.Probability;
import org.uncommons.watchmaker.framework.operators.AbstractCrossover;

/**
 *
 * @author Markus Goetz
 */
public class ScheduleCrossover extends AbstractCrossover<AbstractSchedule> {

    private Collection<Item> rfqs;

    public ScheduleCrossover(Probability probability, Collection<Item> rfqs) {
        super(Integer.MAX_VALUE, probability);
        this.rfqs = rfqs;

    }

    @Override
    protected List<AbstractSchedule> mate(AbstractSchedule s1, AbstractSchedule s2, int crossoverPoints, Random random) {

        double overplanRatio = s1.getOverplanRatio();
        int currentDate = s1.getCurrentDate();

        CrossoverSchedule o1 = new CrossoverSchedule(overplanRatio, currentDate, random);
        CrossoverSchedule o2 = new CrossoverSchedule(overplanRatio, currentDate, random);
        
        Set<Item> o1UnplacedRfqs = new HashSet(rfqs);
        Set<Item> o2UnplacedRfqs = new HashSet(rfqs);

        List<Item> o1ToPlaceRfqs = new LinkedList();
        List<Item> o2ToPlaceRfqs = new LinkedList();
        
        for (int i = 0; i < AbstractSchedule.DAYS_TO_BE_PLANNED; i++) {
            int date = currentDate + i;
            
            Day d1 = s1.getDay(date);
            Day d2 = s2.getDay(date);

            o1.placeOrders(date, d2.getOrders());
            o1ToPlaceRfqs.addAll(d1.getRfqs());

            o2.placeOrders(date, d1.getOrders());
            o2ToPlaceRfqs.addAll(d2.getRfqs());
        }

        o1UnplacedRfqs.removeAll(o1ToPlaceRfqs);
        o1.fillWith(o1ToPlaceRfqs);
        o1.fillWith(new LinkedList(o1UnplacedRfqs));

        o2UnplacedRfqs.removeAll(o2ToPlaceRfqs);
        o2.fillWith(o2ToPlaceRfqs);
        o2.fillWith(new LinkedList(o2UnplacedRfqs));
        
        return Arrays.asList(new AbstractSchedule[] { o1, o2 });
    }
}
